package com.nulldev.util.codecs.uniapi;

import java.nio.charset.CharacterCodingException;
import java.util.Iterator;

import com.nulldev.util.codecs.data.impl.Base64Decoder;
import com.nulldev.util.codecs.data.impl.Base64Encoder;
import com.nulldev.util.data.Arrays.misc.CircularIterator;
import com.nulldev.util.data.Base64.Base64;
import com.nulldev.util.data.Charsets.CharsetUtil;
import com.nulldev.util.internal.backport.concurrency9.Lists;

public class UniBase64 {
	// FIXME: Should we use a circular queue instead of round robin?

	private static final Iterator<Base64Decoder> DECODER_SESSIONS = new CircularIterator<Base64Decoder>(
			Lists.of(new Base64Decoder(), new Base64Decoder(), new Base64Decoder(), new Base64Decoder(), new Base64Decoder(), new Base64Decoder()));
	private static final Iterator<Base64Encoder> ENCODER_SESSIONS = new CircularIterator<Base64Encoder>(
			Lists.of(new Base64Encoder(), new Base64Encoder(), new Base64Encoder(), new Base64Encoder(), new Base64Encoder(), new Base64Encoder()));

	public static String decodeToString(final String b64) {
		try {
			return new String(DECODER_SESSIONS.next().decodeToBytes(b64), CharsetUtil.UTF_8);
		} catch (CharacterCodingException e) {
			return Base64.decodeBase64S(b64);
		}
	}

	public static byte[] decodeToBytes(final String b64) {
		try {
			return DECODER_SESSIONS.next().decodeToBytes(b64);
		} catch (CharacterCodingException e) {
			return Base64.decodeBase64(b64);
		}
	}

	public static String encodeFromBytes(final byte[] data) {
		try {
			return ENCODER_SESSIONS.next().encodeToString(data);
		} catch (CharacterCodingException e) {
			return Base64.encodeBase64String(data);
		}
	}

	public static String encodeFromString(final String data) {
		try {
			return ENCODER_SESSIONS.next().encodeToString(data.getBytes(CharsetUtil.UTF_8));
		} catch (CharacterCodingException e) {
			return Base64.encodeBase64S(data);
		}
	}
}
